/**
 * 
 */
package br.com.lazyprogrammer.social.infestit.network;

import android.util.Log;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.SocketTimeoutException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;

/**
 * 
 * @author Limao Games <br />
 * <b>Email:</b> andreikeda@limaogames.com.br <br />
 * created on: 07/05/2014
 * @version 1.0
 * @see 
 */
public class Request {

    private final int BUFFER_SIZE_8K = 8152;
	
	public enum Response {
		Success,
		ServerError,
		AlreadyRegistered,
		TypeMismatch,
		SocketTimeout,
		UnsupportedEncoding,
		ClientProtocol,
		IllegalState,
		NullPointer,
		IO,
		JSON,
		UnableConnectDatabase,
        NoNetworkConnection
	}

    public interface Callback {
        public void onCancel(Class<?> executingClass);

        public void onStart(Class<?> executingClass);

        public void onSuccess(Class<?> executingClass, Object result);

        public void onError(Class<?> executingClass, Response response, String errorMessage);
    }

	public JSONObject post(String url, Map<String, Object> params)
			throws UnsupportedEncodingException, ClientProtocolException,
			IOException, JSONException, SocketTimeoutException,
			IllegalStateException, NullPointerException {

		StringBuilder json = makeRequestPost(url, params);
		return new JSONObject(json.toString());
	}

	private StringBuilder makeRequestPost(String url,
			Map<String, Object> params) throws UnsupportedEncodingException,
			ClientProtocolException, IOException, JSONException,
			SocketTimeoutException, IllegalStateException, NullPointerException {

		HttpPost httpPost;
		HttpContext localContext = new BasicHttpContext();
		HttpParams httpParams = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(httpParams, 15000);
		HttpConnectionParams.setSoTimeout(httpParams, 15000);

		HttpClient httpClient = new DefaultHttpClient(httpParams);

		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
		if (params != null) {
			for (String key : params.keySet()) {
				nameValuePairs.add(new BasicNameValuePair(key, String
						.valueOf(params.get(key))));
			}
		}

		httpPost = new HttpPost(url.replaceAll("\\s", "_"));
		httpPost.addHeader("Accept-Encoding", "gzip");
		httpPost.setHeader("Content-Type",
                "application/x-www-form-urlencoded;charset=UTF-8");
		httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs,"UTF-8"));

		HttpResponse response = httpClient.execute(httpPost, localContext);
		Header contentEncoding = response.getFirstHeader("Content-Encoding");

		InputStream instream = response.getEntity().getContent();

		if (contentEncoding != null
				&& contentEncoding.getValue().equalsIgnoreCase("gzip")) {
			instream = new GZIPInputStream(instream);
		}

		BufferedReader reader = new BufferedReader(new InputStreamReader(
				instream, "utf-8"), BUFFER_SIZE_8K);
		StringBuilder json = new StringBuilder();
		String line = reader.readLine();

		while (line != null) {
			json.append(URLDecoder.decode(line.replaceAll("%", "%25"), "utf-8"));
			json.append(line);
			line = reader.readLine();
		}
		reader.close();
		
		Log.i(Request.class.getSimpleName(), json.toString());
		return json;
	}

}
